/*!
 * \file frhash2.h
 *
 * \brief hash表操作
 *
 * All Rights Reserved Copyright (C) 2014 broada,Co.,Ltd.\n
 * 结构体和相关接口，实现hash表的操作
 *
 * \version 2.0
 * \author yaohl
 * \date 2014/11/12
 *
 */

#ifndef __FRHASH2_H_
#define __FRHASH2_H_

#include "frlist.h"

/*! @brief hash表头 */
typedef struct __st_hash {
    unsigned long   ul_hash_size;        /*!< 数组长度 */
    unsigned long   ul_node_count;       /*!< 数据个数 */
    Frlist_header  *p_list_array;

} Frhash_header;

/*!
 * 生成哈希key
 *
 * \param p_data    (生成hash key的数据)
 * \param ui_len    (生成hash key数据长度)
 *
 * \return hash key
 *
 * \note DJBHash
 *
 */
unsigned long frhash_key(unsigned char *p_data, unsigned int ui_len);

/*!
 * 生成指定hash表
 *
 * \param p_hash_hdr   (*Frhash_header)
 * \param ul_hash_size (hash 数组的大小)
 *
 * \return FR_SUCC:成功\n
 *         FR_FAIL:失败
 *
 */
int frhash2_create(Frhash_header *p_hash_hdr, unsigned long ul_hash_size);

/*!
 * 生成指定hash表
 *
 * \param p_hash_hdr   (*Frhash_header)
 * \param ul_hash_size (hash 数组的大小)
 *
 * \return 成功时返回hash表头, 否则返回NULL
 *
 * \note 使用frhash_free2释放
 *
 */
Frhash_header *frhash2_create2(unsigned long ul_hash_size);

/*!
 * 释放指定hash表
 *
 * \param p_hash_hdr   (*Frhash_header)
 * \param pf_free      (释放资源用函数指针)
 *
 */
void frhash2_free(Frhash_header *p_hash_hdr, list_node_free pf_free);

/*!
 * 释放指定hash表
 *
 * \param p_hash_hdr   (*Frhash_header)
 * \param pf_free      (释放资源用函数指针)
 *
 * \note 使用frhash_create2生成hash头时,需要用该函数释放
 *
 */
void frhash2_free2(Frhash_header *p_hash_hdr, list_node_free pf_free);

/* i_loop循环用变量,p_hash_hdr hash表指针, p_lst_hdr_tmp链表用临时变量 */
#define FRHASH_LOOP(i_loop,p_hash_hdr, p_lst_hdr_tmp)  \
        for(i_loop=0; i_loop < (p_hash_hdr)->ul_hash_size && (p_lst_hdr_tmp = &((p_hash_hdr)->p_list_array[i_loop]) ); i_loop++)

/*!
 * 向指定hash表里增加数据
 *
 * \param p_hash_hdr   (*Frhash_header)
 * \param ul_key       (key)
 * \param ui_key_len   (key 长度)
 * \param p_st_node_add(hash 里增加的节点)
 *
 * \return FR_SUCC:成功\n
 *         FR_FAIL:失败
 *
 * \note p_st_node需要外部生成
 *
 */
int frhash2_addStr(Frhash_header *p_hash_hdr, const char *p_key, unsigned int ui_key_len, Frlist_node *p_st_node_add);

/*!
 * hash表里查询指定节点
 *
 * \param p_hash_hdr   (*Frhash_header)
 * \param p_key        (key)
 * \param ui_key_len   (key 长度)
 *
 * \return 成功返回Frlist_node *,否则返回NULL
 *
 */
Frlist_node *frhash2_getStr(Frhash_header *p_hash_hdr, const char *p_key, unsigned int ui_key_len);

/*!
 * hash表里释放指定节点
 *
 * \param p_hash_hdr   (*Frhash_header)
 * \param ul_key       (key)
 * \param ui_key_len   (key 长度)
 * \param pf_free      (释放资源用函数指针)
 *
 * \return FR_SUCC:成功\n
 *         FR_FAIL:失败
 *
 */
int frhash2_delStr(Frhash_header *p_hash_hdr, char *p_key, unsigned int ui_key_len, list_node_free pf_free);

/*!
 * 向指定hash表里增加数据
 *
 * \param p_hash_hdr   (*Frhash_header)
 * \param l_key        (key)
 * \param p_st_node_add(hash 里增加的节点)
 *
 * \return FR_SUCC:成功\n
 *         FR_FAIL:失败
 *
 * \note p_st_node需要外部生成
 *
 */
int frhash2_addLong(Frhash_header *p_hash_hdr, long l_key, Frlist_node *p_st_node_add);

/*!
 * hash表里查询指定节点
 *
 * \param p_hash_hdr   (*Frhash_header)
 * \param l_key        (key)
 *
 * \return 成功返回Frlist_node *,否则返回NULL
 *
 */
Frlist_node *frhash2_getLong(Frhash_header *p_hash_hdr, long l_key);

/*!
 * hash表里释放指定节点
 *
 * \param p_hash_hdr   (*Frhash_header)
 * \param ul_key       (key)
 * \param ui_key_len   (key 长度)
 * \param pf_free      (释放资源用函数指针)
 *
 * \return FR_SUCC:成功\n
 *         FR_FAIL:失败
 *
 */
int frhash2_delLong(Frhash_header *p_hash_hdr, long l_key, list_node_free pf_free);

/*!
 * hash表里查询指定节点
 *
 * \param p_hash_hdr   (*Frhash_header)
 * \param p_data       (比较用数据)
 * \param pf_find      (比较用函数指针)
 *
 * \return 成功返回Frlist_node *,否则返回NULL
 *
 * \note 对整个hash表进行查询，需要注意性能问题
 *
 */
Frlist_node *frhash2_find(Frhash_header *p_hash_hdr, void *p_data, list_node_find pf_find);

/*!
 * hash表里查询指定节点
 *
 * \param p_hash_hdr   (*Frhash_header)
 * \param p_key        (key)
 * \param ui_key_len   (key 长度)
 * \param p_data       (比较用数据)
 * \param pf_find      (比较用函数指针)
 *
 * \return 成功返回Frlist_node *,否则返回NULL
 *
 * \note 对整个hash表进行查询，需要注意性能问题
 *
 */
Frlist_node *frhash2_find_strKey(Frhash_header *p_hash_hdr, char *p_key, unsigned int ui_key_len
                               , void *p_data, list_node_find pf_find);

/*!
 * hash表里释放指定节点
 *
 * \param p_hash_hdr   (*Frhash_header)
 * \param p_st_node_del(需要删除的节点)
 * \param pf_free      (释放资源用函数指针)
 *
 * \return FR_SUCC:成功\n
 *         FR_FAIL:失败
 *
 */
int frhash2_del(Frhash_header *p_hash_hdr, Frlist_node *p_st_node_del, list_node_free pf_free);

/*!
 * 指定节点从hash表里脱离
 *
 * \param p_hash_hdr   (*Frhash_header)
 * \param p_st_node_apart(要脱离节点)
 *
 * \return FR_SUCC:成功\n
 *         FR_FAIL:失败
 *
 */
int frhash2_apart(Frhash_header *p_hash_hdr, Frlist_node *p_st_node_apart);


/*!
 * hash表内容出力
 *
 * \param p_hash_hdr   (*Frhash_header)
 * \param p_outbuff    (出力数据用空间)
 * \param ui_buff_size (出力数据用空间大小)
 * \param pf_show      (出力节点用函数指针)
 *
 * \note 内容输出到p_outbuff的空间，有长度限制。(有内容截断的情况)
 *
 */
void frhash2_show(Frhash_header *p_hash_hdr, char *p_outbuff, unsigned int ui_buff_size, list_node_show pf_show);

/*!
 * hash表内容出力
 *
 * \param p_hash_hdr   (*Frhash_header)
 * \param pp_outbuff   (出力数据用空间)
 * \param pf_show      (出力节点用函数指针)
 *
 * \note pp_outbuff内存空间在该函数内部生成,需要在外部释放
 *
 */
void frhash2_show_all(Frhash_header *p_hash_hdr, char **pp_outbuff, list_node_show_all pf_show);

/*!
 * hash表内容出力 每个节点的长度分配为最大2048，超过2048请使用frhash2_show_all
 *
 * \param p_hash_hdr   (*Frhash_header)
 * \param pp_outbuff   (出力数据用空间)
 * \param pf_show      (出力节点用函数指针)
 *
 * \note pp_outbuff内存空间在该函数内部生成,需要在外部释放
 *
 */
void frhash2_show_all2(Frhash_header *p_hash_hdr, char **pp_outbuff, list_node_show pf_show);

/*!
 * 对hash表内容里运行所有函数指针
 *
 * \param p_hash_hdr   (*Frhash_header)
 * \param p_data       (函数指针用数据，如果没有设置为NULL)
 * \param pf_run       (运行用函数指针)
 *
 * \return 0:pf_run控制退出; 1:运行到最后
 *
 */
void frhash2_run(Frhash_header *p_hash_hdr, void *p_data, list_node_run pf_run);

/*!
 * 获取hash表数据个数
 *
 * \param p_hash_hdr   (*Frhash_header)
 *
 * \return hash表数据个数
 *
 */
unsigned long frhash2_getCount(Frhash_header *p_hash_hdr);

/* 释放节点的data数据 */
#define frhash2_node_data_free frlist_node_data_free

#endif
